package com.qf.scms.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qf.scms.dao.CourseDao;
import com.qf.scms.dao.SelCourseDao;
import com.qf.scms.entity.Course;
import com.qf.scms.entity.SelCourse;
import com.qf.scms.entity.User;
import com.qf.scms.param.SelCourseParam;
import com.qf.scms.service.SelCourseService;
import com.qf.scms.utils.TokenUtils;
import com.qf.scms.vo.CourseVO;
import com.qf.scms.vo.SelCourseCalculateVO;
import com.qf.scms.vo.SelCourseVO;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (SelCourse)表服务实现类
 *
 * @author makejava
 * @since 2025-06-28 09:44:52
 */
@Service("selCourseService")
public class SelCourseServiceImpl implements SelCourseService {
    @Resource
    private SelCourseDao selCourseDao;

    @Resource
    private CourseDao courseDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SelCourse queryById(Integer id) {
        return this.selCourseDao.queryById(id);
    }


    /**
     * 分页查询
     *
     * @param selCourseParam 筛选条件
     * @return 查询结果
     */
    @Override
    public Page<SelCourseVO> queryByPage(SelCourseParam selCourseParam) {
        // 1. 创建分页对象
        Page<User> userPage = new Page<>(selCourseParam.getPageNum(), selCourseParam.getPageSize());
        Page<SelCourseVO> resultPage = new Page<>();

        // 2. 查询学生ID
        List<Integer> stuIds = selCourseDao.queryStuIdsByCid(selCourseParam.getCid());

        // 对查询出来的学生ID进行判断
        if (stuIds.isEmpty()) {
            // 说明学生没有选课，则直接进行返回
            resultPage.setTotal(0);
            resultPage.setRecords(null);
            return resultPage;
        }

        // 3. 数据库分页查询学生信息
        IPage<User> userIPage = selCourseDao.queryStudentsByStuIds(userPage, stuIds);

        // 4. 转换为 VO
        List<SelCourseVO> selCourseVOS = userIPage.getRecords().stream()
                .map(student -> {
                    SelCourseVO selCourseVO = new SelCourseVO();
                    selCourseVO.setStuName(student.getUsername());
                    selCourseVO.setSid(student.getId().toString());
                    return selCourseVO;
                })
                .collect(Collectors.toList());

        // 4. 根据stuIds的长度计算出选课人数
        // 5. 构建返回的 Page 对象

        resultPage.setRecords(selCourseVOS);
        resultPage.setTotal(userIPage.getTotal());
        resultPage.setCurrent(userIPage.getCurrent());
        resultPage.setSize(userIPage.getSize());
        resultPage.setPages(userIPage.getPages());

        return resultPage;
    }


    /**
     * 新增数据
     *
     * @param selCourse 实例对象
     * @return 实例对象
     */
    @Override
    public SelCourse insert(SelCourse selCourse) {
        this.selCourseDao.insert(selCourse);
        return selCourse;
    }

    /**
     * 修改数据
     *
     * @param selCourse 实例对象
     * @return 实例对象
     */
    @Override
    public SelCourse update(SelCourse selCourse) {
        this.selCourseDao.update(selCourse);
        return this.queryById(selCourse.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.selCourseDao.deleteById(id) > 0;
    }

    /**
     * 删除选课记录信息
     *
     * @param sid 学生id
     * @param cid 课程id
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteSelCourseRecordBySid(String sid, String cid) {
        // 获取当前用户的sid
        return selCourseDao.deleteSelCourseRecordBySid(sid, cid) > 0;
    }

    /**
     * 选课信息统计
     *
     * @param cid 课程id
     * @return 选课信息统计结果
     */
    @Override
    public SelCourseCalculateVO selCourseCalculate(String cid) {
        // 判断参数是否为空
        if (cid == null) {
            throw new IllegalArgumentException("参数不能为空!");
        }
        // 判断前端传递的课程id参数类型是否正确
        if (!(cid instanceof String)) {
            throw new IllegalArgumentException("课程id数据类型错误!");
        }

        // 第一步：根据课程id，计算出选课人数
        List<Integer> stuIds = selCourseDao.queryStuIdsByCid(cid);
        Integer courseNum = stuIds.size();
        SelCourseCalculateVO selCourseCalculateVO = new SelCourseCalculateVO();
        selCourseCalculateVO.setCourseSelectedNum(courseNum);
        // 第二步：根据课程id主键，查询出课程信息
        Course course = courseDao.queryById(Integer.valueOf(cid));
        // 获取课程的教室容量并设置到SelCourseCalculateVO中
        selCourseCalculateVO.setCourseCapacity(course.getSize());
        // 返回结果
        return selCourseCalculateVO;
    }

    /**
     * 学生选课
     *
     * @param selCourseParam 选课参数
     * @return 选课结果
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Boolean studentSelectCourse(SelCourseParam selCourseParam) {
        // 判断选课参数是否为null
        if (selCourseParam.getCid() == null) {
            throw new RuntimeException("选课参数为null");
        }

        // 获取当前用户的id
        Integer uid = TokenUtils.getUidFromToken();

        // 第一步：判断当前用户是否已经选过该课程
        Integer isSelected = selCourseDao.queryBySidAndCid(uid.toString(), selCourseParam.getCid());
        if (isSelected > 0){
            throw new RuntimeException("该用户已经选过该课程");
        }

        // 第二步：获取有多少人选择了该课程
        SelCourse selCourse = new SelCourse();
        selCourse.setSid(uid.toString());
        selCourse.setCid(selCourseParam.getCid());
        Integer courseNum = selCourseDao.countCourseNumByCid(selCourseParam.getCid());
        // 然后判断选择这门课的人数是否超过了教室的容量了
        Course course = courseDao.queryById(Integer.valueOf(selCourseParam.getCid()));
        if (course.getSize() < courseNum){
            throw new RuntimeException("所选课程已满");
        }

        // 第三步：查询该学生选择了几门课了，是否超过了5门
        Integer studentNum = selCourseDao.queryBySidAndCid(uid.toString(), selCourseParam.getCid());
        if (studentNum >= 5){
            throw new RuntimeException("您已经选购5门课程了");
        }

        // 第四步：插入选课记录
        int result = selCourseDao.insert(selCourse);
        if (result <= 0){
            throw new RuntimeException("选课失败");
        }
        return true;
    }

    /**
     * 查询当前学生的选课记录
     * @param selCourseParam 选课参数
     * @return 选课记录
     */
    @Override
    public IPage<CourseVO> queryStuSelCourseByPage(SelCourseParam selCourseParam) {
        Page<Course> coursePage = new Page<>(selCourseParam.getPageNum(), selCourseParam.getPageSize());

        // 获取当前学生的id
        String sid = TokenUtils.getUidFromToken().toString();

        // 根据学生id，查询该学生的所有课程id
        IPage<CourseVO> page = selCourseDao.queryStuSelCourseByPage(coursePage, sid);
        // 转化为VO列表
        List<CourseVO> courseVOS = page.getRecords().stream().map(Course -> {
            // 创建一个VO对象
            CourseVO courseVO1 = new CourseVO();
            courseVO1.setId(Course.getId());
            courseVO1.setName(Course.getName());
            courseVO1.setTeacher(Course.getTeacher());
            courseVO1.setSize(Course.getSize());
            return courseVO1;
        }).collect(Collectors.toList());
        // 构建page对象并返回
        page.setRecords(courseVOS);
        page.setTotal(coursePage.getTotal());
        page.setCurrent(coursePage.getCurrent());
        page.setSize(coursePage.getSize());
        return page;

    }


}
